package com.fastloan.safe.mgt.login.service.impl;

import com.fastloan.safe.core.param.RoleTypeEnum;
import com.fastloan.safe.core.shiro.ShiroRedisClient;
import com.fastloan.safe.core.util.ManagerKit;
import com.fastloan.safe.mgt.auth.model.CmuRole;
import com.fastloan.safe.mgt.auth.service.CmuRoleService;
import com.fastloan.safe.mgt.login.service.LoginService;
import com.fastloan.safe.mgt.org.model.CmuOrg;
import com.fastloan.safe.mgt.org.service.CmuOrgService;
import com.fastloan.safe.mgt.root.model.CmDefResApi;
import com.fastloan.safe.mgt.root.model.CmDefRole;
import com.fastloan.safe.mgt.root.service.CmDefResApiService;
import com.fastloan.safe.mgt.root.service.CmDefRoleService;
import com.fastloan.safe.mgt.user.dao.CmuUserMapper;
import com.fastloan.safe.mgt.user.model.CmuUser;
import com.kawins.base.share.BaseConstant;
import com.kawins.result.ResultEnum;
import com.kawins.result.ResultTo;
import com.kawins.shiro.temp.achieve.AuthorizationManager;
import com.kawins.shiro.temp.core.filter.FormAuthFilter;
import com.kawins.shiro.temp.core.manager.AuthenticationTokenInfo;
import com.kawins.shiro.temp.core.result.ShiroResultEnum;
import com.kawins.shiro.temp.util.ShiroKit;
import com.kawins.supers.notice.sms.ISendSms;
import com.kawins.util.IDCardUtil;
import com.kawins.util.ValidUtil;
import com.kawins.util.VerifyCodeUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author rankai
 *         createTime 2017-09-2017/9/25 16:20
 */
public class LoginServiceImpl implements LoginService {

    private static final Logger log = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Autowired
    private CmuUserMapper userMapper;

    @Autowired
    private CmDefRoleService defRoleService;

    @Autowired
    private CmuRoleService cmuRoleService;

    @Autowired
    private CmDefResApiService defResApiService;

    @Autowired
    private CmuOrgService orgService;

    @Autowired
    private ISendSms sendSms;

    @Autowired
    private ShiroRedisClient shiroRedisClient;

    @Override
    public CmuUser selectByUsername(String s) {
        CmuUser user = new CmuUser();
        user.setUsername(s);
        return userMapper.selectOne(user);
    }

    @Override
    public CmuUser selectByEmail(String s) {
        CmuUser user = new CmuUser();
        user.setEmail(s);
        return userMapper.selectOne(user);
    }

    @Override
    public CmuUser selectByPhone(String s) {
        CmuUser user = new CmuUser();
        user.setPhone(s);
        return userMapper.selectOne(user);
    }

    @Override
    public Set<String> selectRole(String userName) {
        CmuUser user = new CmuUser();
        user.setUsername(userName);
        CmuUser usUser = userMapper.selectOne(user);
        List<String> list = null;
        if (StringUtils.isNotBlank(usUser.getRootRoleId())) {
            CmDefRole cmDefRole = defRoleService.selectByPrimaryKey(usUser.getRootRoleId());
            if (list == null) {
                list = new ArrayList<>();
            }
            list.add(cmDefRole.getName());
        } else {
            list = cmuRoleService.selectRole(usUser.getId());
        }
        return new HashSet<>(list);
    }

    @Override
    public Set<String> selectAuthority(String userName) {
        CmuUser user = new CmuUser();
        user.setUsername(userName);
        CmuUser usUser = userMapper.selectOne(user);
        List<CmDefResApi> usDefResApi;
        if (StringUtils.isNotBlank(usUser.getRootRoleId())) {
            usDefResApi = defResApiService.selectAuthForRoot(usUser.getId());
        } else {
            usDefResApi = defResApiService.selectAuth(usUser.getId());
        }
        Set<String> set = new HashSet<>();
        for (CmDefResApi usDefRe : usDefResApi) {
            set.add(usDefRe.getMethod() + ":" + usDefRe.getName());
        }
        return set;
    }

    @Override
    public void rememberMe(ServletRequest servletRequest) {

    }

    @Override
    public void loginSuccess(boolean isCustomer) {
        if (!isCustomer) {
            Session session = ManagerKit.getSession();
            String userId = ManagerKit.getUserId();
            CmuUser cmuUser = userMapper.selectByPrimaryKey(userId);
            session.setAttribute(BaseConstant.USER_ID_SESSION_KEY, cmuUser.getId());
            session.setAttribute(ManagerKit.LOGIN_USER, cmuUser);
            if (StringUtils.isBlank(cmuUser.getRootRoleId())) {
                String orgId = orgService.selectOrgByUser(userId);
                session.setAttribute(ManagerKit.ORG_ID, orgId);
                List<CmuOrg> cmuOrgs = orgService.selectTopOrgBySon(orgId, false, true);
                session.setAttribute(ManagerKit.TOP_ORG_ID, cmuOrgs.size() > 0 ? cmuOrgs.get(0).getId() : null);
                List<CmuRole> cmuRoles = cmuRoleService.selectByUserId(userId);
                session.setAttribute(ManagerKit.ROLE_BEAN, cmuRoles.size() > 0 ? cmuRoles.get(0) : null);
            }
        }
    }

    @Override
    public boolean cusLogin(String userName, String code, Integer loginType, Integer type) {
        log.debug("收到客户登陆请求,客户手机号:{}", userName);
        AuthenticationTokenInfo token = new AuthenticationTokenInfo();
        token.setCodeUserName(userName);
        token.setCodeValue(code);
        token.setLoginTypes(new String[]{String.valueOf(loginType)});
        shiroRedisClient.set(AuthorizationManager.DEFAULT_REDIS_CODE_KEY + userName, code, 5 * 60);
        Session session = ShiroKit.getSession();
        session.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
                ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
        ShiroKit.login(token);
        log.debug("获取当前登陆客户的ID:{}", ManagerKit.getCustomerId());
        return true;
    }

    @Override
    public ResultTo login(HttpServletRequest request, Integer type) {
        AuthenticationTokenInfo token = (AuthenticationTokenInfo) request.getAttribute(FormAuthFilter.SHIRO_LOGIN_FAILURE);
        if (token == null) {
            return new ResultTo(ResultEnum.PARAM_ERROR);
        }
        ShiroKit.login(token);
        if (type == null) {
            loginSuccess(false);
            CmuUser user = ManagerKit.getUser();
            user.setLastLoginTime(new Date());
            userMapper.updateByPrimaryKeySelective(user);
            return new ResultTo(ShiroResultEnum.LOGIN_SUCCESS.getCode(), ShiroResultEnum.LOGIN_SUCCESS.getMessage());
        } else if (type != -1) {
            loginSuccess(false);
            if (!ManagerKit.getRole().getIndexType().equals(type)) {
                ShiroKit.logout();
                return new ResultTo(600, "你没有[" + RoleTypeEnum.getNameByCode(type) + "]的类型");
            }
            Map<String, Object> map = new HashMap<>(2);
            map.put("tokenId", ManagerKit.getSession().getId());
            CmuUser user = ManagerKit.getUser();
            map.put("userBean", user);
            map.put("sex", IDCardUtil.getSexByIDCard(user.getIdCard()).getCode());
            return new ResultTo(ShiroResultEnum.LOGIN_SUCCESS.getCode(), ShiroResultEnum.LOGIN_SUCCESS.getMessage()).setData(map);
        } else {
            loginSuccess(true);
            return new ResultTo(ShiroResultEnum.LOGIN_SUCCESS.getCode(), ShiroResultEnum.LOGIN_SUCCESS.getMessage()).setData("tokenId", ManagerKit.getSession().getId());
        }
    }

    @Override
    public ResultTo sendCode(String value) {
        if (ValidUtil.validEmail(value)) {
            log.debug("验证码发送目标为邮箱　>> {}", value);
        } else if (ValidUtil.validPhone(value)) {
            log.debug("验证码发送目标为手机号　>> {}", value);
            String defaultRedisCodeKey = AuthorizationManager.DEFAULT_REDIS_CODE_KEY;
            Object object = shiroRedisClient.get(defaultRedisCodeKey + value);
            String textCode;
            if (object != null) {
                textCode = object.toString();
                shiroRedisClient.expire(defaultRedisCodeKey + value, 3 * 60);
            } else {
                textCode = VerifyCodeUtil.generateTextCode(VerifyCodeUtil.TYPE_NUM_ONLY, 6, null);
            }
            log.debug("验证码为 >> {}", textCode);
            shiroRedisClient.set(defaultRedisCodeKey + value, textCode, 3 * 60);
            sendSms.send(value, textCode);
        } else {
            return new ResultTo(ResultEnum.PARAM_ERROR, "非手机号或者邮箱");
        }
        return new ResultTo();
    }
}
